/*--- lldriver.c -------------------------- Listing 2-5 -------
 *  Reads in text words from the file specified on the command
 *  line and places them into two linked lists. Then exercises
 *  a variety of linked-list activities, printing the results
 *  at every step.
 *  Must be linked to linked-list primitives in Listings 2-2
 *  through 2-4b.
 *-------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "llgen.h"          /* Header for generic linked lists */
#include "llapp.h"          /* Header for appl.'s linked lists */

int main(int argc, char *argv[])
{
    char word[64];          /* the raw word from the file */
    int count;

    struct List *L1, *L2;   /* two different linked lists */
    Link w1, w2, w3;        /* cursors used to walk lists */

    FILE *fin;              /* the input file             */

    if (argc != 2) {
        fprintf(stderr, "Error! Usage: lldriver filename\n");
        exit(EXIT_FAILURE);
    }

    fin = fopen(argv[1], "rt");
    if (fin == NULL) {
        fprintf(stderr, "Could not find/open %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    /*--- set up linked-list data structures ---*/
    L1 = CreateLList(CreateData1,       /* in llapp.c */
                     DeleteData1,       /*     "      */
                     DuplicatedNode1,   /*     "      */
                     NodeDataCmp1);     /*     "      */

    L2 = CreateLList(CreateData2,       /* in llapp.c */
                     DeleteData2,       /*     "      */
                     DuplicatedNode2,   /*     "      */
                     NodeDataCmp2);     /*     "      */

    if (L1 == NULL || L2 == NULL) {
        fprintf(stderr, "Error creating linked list\n");
        exit(EXIT_FAILURE);
    }

    /*--- begin processing file ---*/
    while (fgets(word, 64, fin) != NULL) {
        if (strlen(word) > 0)
            word[strlen(word) - 1] = 0; /* strip tail \n */

        /* now, add the word to both lists */
        if (!AddNodeAscend(L1, word))
            fprintf(stderr,
                    "Warning! Error while adding node to L1.\n");
        if (!AddNodeAtHead(L2, word))
            fprintf(stderr,
                    "Warning! Error while adding node to L2.\n");
    }
    fclose(fin);

    /* now, walk the lists */
    printf("L1 contains %u items:\n", L1->LCount);
    for (w1 = L1->LHead; w1 != NULL; w1 = w1->next)
         printf("  %s occured %d times.\n",
                ((pND1)(w1->pdata))->word,
                ((pND1)(w1->pdata))->u);

    printf("L2 contains %u items:\n", L2->LCount);
    for (w1 = L2->LHead; w1 != NULL; w1 = w1->next)
        printf("  %s\n", ((pND2)(w1->pdata))->word);

    /* both ways at once */
    printf("L2 contains %u items:\n", L2->LCount);
    w1 = L2->LHead;
    w2 = L2->LTail;
    for ( ; w1 != NULL && w2 != NULL;
         w1 = w1->next, w2 = w2->prev)
        printf("  %30s  %30s\n",
               ((pND2)(w1->pdata))->word,
               ((pND2)(w2->pdata))->word);

    /* "Find" each node and delete every other one */
    count = 0;
    w1 = L2->LHead;
    while (w1 != NULL) {
        w3 = FindNode(L2, w1->pdata);
        if (w3 != 0) {
            printf("Found node %s", ((pND2)(w3->pdata))->word);
            count += 1;
            w1 = w3->next;
            if (count & 1) {
                DeleteNode(L2, w3);
                printf(" and deleted it.");
            }
            printf( "\n");
        } else
            w1 = NULL;
    }

    printf("L2 contains %u items:\n", L2->LCount);
    w1 = L2->LHead;
    w2 = L2->LTail;
    for ( ; w1 != NULL && w2 != NULL;
         w1 = w1->next, w2 = w2->prev)
        printf("  %30s  %30s\n",
               ((pND2)(w1->pdata))->word,
               ((pND2)(w2->pdata))->word);

    return(EXIT_SUCCESS);
}
